package com.melodyframe.stage.web;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.melodyframe.common.context.ContextLocal;
import com.melodyframe.stage.core.Stage;
import com.melodyframe.stage.core.renderer.View;
import com.melodyframe.stage.web.context.RequestContextLocal;

public class StageDispatchFilter implements Filter {
	private Stage	stage;

	public boolean hasStage() {
		return null != this.getStage();
	}

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		if (request instanceof HttpServletRequest
				&& response instanceof HttpServletResponse) {
			HttpServletRequest httpRequest = (HttpServletRequest) request;
			HttpServletResponse httpResponse = (HttpServletResponse) response;
			ContextLocal.reset();
			this.initContext(httpRequest, httpResponse);
			if (this.hasStage()) {// Perform stage if had
				if (this.perform(httpRequest, httpResponse)) {
					return;
				}
			}

		}
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
	}

	/**
	 * Initialize request context
	 * 
	 * @param request
	 * @param response
	 */
	private void initContext(HttpServletRequest request,
			HttpServletResponse response) {
		RequestContextLocal.bind(request, response);
	}

	/**
	 * Do perform
	 * 
	 * @param request
	 * @param response
	 */
	private boolean perform(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		String path = request.getRequestURI().substring(
				request.getContextPath().length());

		View view = this.getStage().perform(path, ContextLocal.getContext());
		if (null != view) {
			response.reset();
			PrintWriter out = response.getWriter();
			out.print(view.getResponseText());
			out.flush();
			out.close();
			return true;
		} else {
			return false;
		}
	}

	public Stage getStage() {
		return stage;
	}

	public void setStage(Stage stage) {
		this.stage = stage;
	}

}
